package gov.pbc.nn.kjgl.item.template.view;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.Table;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.bstek.bdf2.core.business.IUser;
import com.bstek.bdf2.core.context.ContextHolder;
import com.bstek.bdf2.core.service.IDeptService;
import com.bstek.dorado.annotation.DataProvider;
import com.bstek.dorado.annotation.DataResolver;
import com.bstek.dorado.annotation.Expose;
import com.bstek.dorado.data.entity.EntityState;
import com.bstek.dorado.data.entity.EntityUtils;
import com.bstek.dorado.data.provider.Criteria;
import com.bstek.dorado.data.provider.Page;
import com.bstek.dorado.util.proxy.ProxyBeanUtils;
import com.bstek.uflo.client.service.ProcessClient;
import com.bstek.uflo.client.service.TaskClient;
import com.bstek.uflo.model.ProcessInstance;
import com.bstek.uflo.model.task.Task;
import com.bstek.uflo.service.ProcessService;
import com.bstek.uflo.service.StartProcessInfo;

import gov.pbc.nn.core.bdf.IUserSelect;
import gov.pbc.nn.core.bdf.entity.Dept;
import gov.pbc.nn.core.dao.CommonJdbcDao;
import gov.pbc.nn.core.dao.PbcnnCoreHibernateDao;
import gov.pbc.nn.core.utils.GetTableUtils;
import gov.pbc.nn.core.utils.SecurityUtils;
import gov.pbc.nn.kjgl.Constants;
import gov.pbc.nn.kjgl.item.template.ItemApprovalWarpper;
import gov.pbc.nn.kjgl.item.template.dao.ItemApprovalDao;
import gov.pbc.nn.kjgl.item.template.entity.AcceptDept;
import gov.pbc.nn.kjgl.item.template.entity.AcceptUser;
import gov.pbc.nn.kjgl.item.template.entity.ItemApproval;
import gov.pbc.nn.kjgl.item.template.entity.ItemName;
import gov.pbc.nn.kjgl.item.template.entity.ItemType;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskByCzService;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskByGiveOpinionService;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskByKzService;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskByShouldStampService;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskBySlCzService;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskBySlZhyCollectOpinionService;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskBySlZhyDisagreeService;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskBySlZhyEndProcessService;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskBySlZhyReCollectOpinionService;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskBySlZhyToLeaderService;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskBySlZhyToNextDeptService;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskByStampService;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskByZhyEndProcessService;
import gov.pbc.nn.kjgl.item.template.service.ICompleteTaskByZhyService;
import gov.pbc.nn.kjgl.item.template.setting.ItemSetting;
import gov.pbc.nn.kjgl.task.entity.TaskEntity;
import gov.pbc.nn.kjgl.task.view.TaskPR;
import gov.pbc.nn.uflo.UfloUtils;
import gov.pbc.nn.uflo.UfloUtils.ProcessState;
import gov.pbc.nn.uflo.entity.Opinion;

@Component
public class ItemApprovalPR implements IUserSelect {

	@Autowired
	private ItemApprovalDao itemApprovalDao;

	@Resource(name = CommonJdbcDao.BEAN_ID)
	private CommonJdbcDao jdbcDao;

	@Resource(name = PbcnnCoreHibernateDao.BEAN_ID)
	private PbcnnCoreHibernateDao coreHibernateDao;

	@Resource(name = ProcessClient.BEAN_ID)
	private ProcessClient pc;

	@Resource(name = TaskClient.BEAN_ID)
	private TaskClient tc;

	@Autowired
	@Qualifier(ProcessService.BEAN_ID)
	private ProcessService processService;

	@DataProvider
	public ItemApproval loadItem(String id) throws Exception {
		if (StringUtils.isEmpty(id)) {
			return null;
		}
		ItemApproval ia = (ItemApproval) this.itemApprovalDao.get(id, ItemApproval.class);
		ia = EntityUtils.toEntity(ia);
		ItemSetting is = this.itemApprovalDao.getItemSeting(ia.getType());
		EntityUtils.setValue(ia, "itemSetting", is);
		return ia;
	}

	@DataProvider
	public void loadItems(Page<ItemApproval> page, Criteria criteria) throws Exception {
		DetachedCriteria dc = this.itemApprovalDao.buildDetachedCriteria(criteria, ItemApproval.class);
		dc.add(Restrictions.eq("invalid", false));
		dc.add(Restrictions.eq("createUser", ContextHolder.getLoginUserName()));
		dc.addOrder(Order.desc("createDate"));

		if (!this.itemApprovalDao.containsProperty("state", criteria)) {
			dc.add(Restrictions.in("state", new Object[] { 10, 0 }));
		}

		dc.addOrder(Order.asc("state"));
		this.itemApprovalDao.pagingQuery(page, dc);
		List<ItemApproval> list = new ArrayList<ItemApproval>();
		for (ItemApproval ia : page.getEntities()) {
			ia = EntityUtils.toEntity(ia);
			EntityUtils.setValue(ia, "itemSetting", this.itemApprovalDao.getItemSeting(ia.getType()));
			list.add(ia);
		}
		page.setEntities(list);
	}

	@DataProvider
	public void loadItemsOfOver(Page<ItemApproval> page, Criteria criteria) throws Exception {
		DetachedCriteria dc = this.itemApprovalDao.buildDetachedCriteria(criteria, ItemApproval.class);
		dc.add(Restrictions.eq("invalid", false));
		dc.add(Restrictions.eq("createUser", ContextHolder.getLoginUserName()));
		dc.add(Restrictions.in("state", new Object[] { 20, 30 }));
		dc.addOrder(Order.desc("createDate"));
		dc.addOrder(Order.desc("state"));
		this.itemApprovalDao.pagingQuery(page, dc);
		List<ItemApproval> list = new ArrayList<ItemApproval>();
		for (ItemApproval ia : page.getEntities()) {
			ia = EntityUtils.toEntity(ia);
			EntityUtils.setValue(ia, "itemSetting", this.itemApprovalDao.getItemSeting(ia.getType()));
			list.add(ia);
		}
		page.setEntities(list);
	}

	/**
	 * 加载受理部门
	 * 
	 * @param itemApprovalId
	 * @return
	 */
	@DataProvider
	public List<AcceptDept> loadAcceptDepts(String itemApprovalId) {
		String hql = "from " + AcceptDept.class.getName() + " where itemApprovalId=:itemApprovalId and invalid=false";
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("itemApprovalId", itemApprovalId);
		List<AcceptDept> list = this.itemApprovalDao.query(hql, params);
		return list;
	}

	/**
	 * 受理部门综合员审核时，加载受理科长信息
	 */
	@DataProvider
	public List<AcceptUser> loadAcceptUsers(String businessId) {
		Dept dept = (Dept) ContextHolder.getLoginUser().getDepts().get(0);
		String deptId = dept.getCDept().getId();
		String hql = "select id from " + AcceptDept.class.getName()
				+ " where itemApprovalId=:itemApprovalId and deptId=:deptId  and invalid=false";
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("itemApprovalId", businessId);
		params.put("deptId", deptId);
		List<String> list = this.itemApprovalDao.query(hql, params);

		String acceptDeptId = list.get(0);
		hql = "from " + AcceptUser.class.getName() + " where acceptDeptId=:acceptDeptId and invalid=false";
		params.clear();
		params.put("acceptDeptId", acceptDeptId);
		return this.itemApprovalDao.query(hql, params);
	}

	@DataProvider
	public Collection<ItemType> loadItemType(String filterValue) throws Exception {
		DetachedCriteria dc = DetachedCriteria.forClass(ItemType.class);
		dc.add(Restrictions.eq("invalid", false));
		if (StringUtils.isNotEmpty(filterValue))
			dc.add(Restrictions.or(Restrictions.like("deptName", filterValue, MatchMode.ANYWHERE),
					Restrictions.like("name", filterValue, MatchMode.ANYWHERE)));
		dc.addOrder(Order.asc("deptId"));
		List<ItemType> list = new ArrayList<ItemType>();
		Collection<ItemType> col = (Collection<ItemType>) this.itemApprovalDao.query(dc);
		for (ItemType it : col) {
			it = EntityUtils.toEntity(it);
			EntityUtils.setValue(it, "itemSetting", this.itemApprovalDao.getItemSeting(it));
			list.add(it);
		}
		return list;
	}

	// @DataProvider
	// public Collection<ItemSetting> loadItemSetting(String deptId) {
	// String hql = "from " + ItemType.class.getName() + " where invalid=0 and
	// deptId=:deptId";
	// Map<String, Object> params = new HashMap<String, Object>();
	// params.put("deptId", deptId);
	// Collection<ItemType> col = this.itemApprovalDao.query(hql, params);
	// List<ItemSetting> list = new ArrayList<ItemSetting>();
	// for (ItemType type : col) {
	// list.add(this.itemApprovalDao.convertToItemSetting(type));
	// }
	// return list;
	// }

	@DataProvider
	public Collection<ItemName> loadItemName(String itemTypeId) {
		String hql = "from " + ItemName.class.getName() + " where invalid=0 and itemTypeId=:itemTypeId";
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("itemTypeId", itemTypeId);
		Collection<ItemName> col = this.itemApprovalDao.query(hql, params);
		return col;
	}

	/**
	 * 提交申请时，加载本部门中具有科长岗位的人
	 * 
	 * @return
	 */
	@DataProvider
	public Collection<IUser> loadKz() {
		return SecurityUtils.getUserByRoleForDept(ContextHolder.getLoginUser().getDepts().get(0).getId(),
				Constants.ROLE_KZ);
	}

	/**
	 * 提交申请时，加载本部门中具有处长岗位的人
	 * 
	 * @return
	 */
	@DataProvider
	public Collection<IUser> loadCz() {
		return SecurityUtils.getUserByRoleForDeptWithChildren(
				((Dept) ContextHolder.getLoginUser().getDepts().get(0)).getCDept().getId(), Constants.ROLE_CZ);
	}

	/**
	 * 获取受理科长的最新的审核意见
	 * 
	 * @param params
	 * @return
	 */
	@DataProvider
	public String getAcceptUserOpinion(Map<String, Object> params) {
		String acceptUserId = (String) params.get("acceptUserId");
		long taskId = Long.parseLong(params.get("taskId").toString());

		Map<String, Object> parameter = new HashMap<String, Object>();
		String hql = "select username from " + AcceptUser.class.getName() + " where id=:acceptUserId and invalid=false";
		parameter.put("acceptUserId", acceptUserId);
		List<String> users = new ArrayList<String>();
		users.add((String) this.itemApprovalDao.query(hql, parameter).get(0));

		Task task = this.tc.getTask(taskId);

		List<Opinion> list = UfloUtils.getLatestOpinions(task.getProcessInstanceId(), task.getBusinessId(), null, null,
				users);
		if (list != null) {
			if (list.size() > 0) {
				return list.get(0).getOpinion();
			}
		}
		return null;
	}

	@DataResolver
	@Transactional
	public String saveItemApproval(ItemApproval ia) throws Exception {
		ItemApprovalWarpper iaw = new ItemApprovalWarpper();
		iaw.setItem((ItemApproval) ProxyBeanUtils.getProxyTarget(ia));
		iaw.setState(EntityUtils.getState(ia));

		List<AcceptDept> depts = EntityUtils.getValue(ia, "acceptDepts");
		if (depts != null) {
			for (AcceptDept dept : depts) {
				iaw.addDept((AcceptDept) ProxyBeanUtils.getProxyTarget(dept), EntityUtils.getState(dept));
			}
		}
		try (ByteArrayOutputStream out = new ByteArrayOutputStream();) {
			ObjectOutputStream os = new ObjectOutputStream(out);
			os.writeObject(iaw);
			ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
			Path target = Files.createTempFile(null, null);
			Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
			return target.getFileName().toString();
		}

	}

	@Expose
	@Transactional
	public void deleteAcceptDept(List<String> idList) {
		for (String id : idList) {
			this.itemApprovalDao.delete(id, AcceptDept.class);
		}
	}

	@Expose
	public String canDelete(String id) {
		ItemApproval ia = this.itemApprovalDao.get(id, ItemApproval.class);
		if (ia.getState() == 20 || ia.getState() == 30) {
			return "当前事项审批流程已结束，不能删除！";
		}
		return null;
	}

	@Expose
	public String canModify(String id) {
		ItemApproval ia = this.itemApprovalDao.get(id, ItemApproval.class);
		if (ia.getState() == 10) {
			return "当前事项审批流程正在审批中，不能修改！";
		}
		if (ia.getState() == 20 || ia.getState() == 30) {
			return "当前事项审批流程已结束，不能删除！";
		}
		return null;
	}

	/**
	 * 删除事项
	 * 
	 * @param id
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void deleteItem(String id) throws Exception {
		String result = this.canDelete(id);
		if (result != null) {
			throw new UnsupportedOperationException(result);
		}
		final ItemApproval ia = (ItemApproval) this.itemApprovalDao.get(id, ItemApproval.class);
		this.itemApprovalDao.delete(ia.getBusKey(), ia.getBusEntityClass());
		this.itemApprovalDao.delete(ia);
		UfloUtils.deleteProcessInstance(ia.getId(), true);
	}

	/**
	 * 发起任务子流程
	 * 
	 * @param taskEntity
	 * @throws Exception
	 */
	@DataResolver
	@Transactional
	public void startTaskSubProcess(TaskEntity taskEntity, Map<String, Object> params) throws Exception {
		String taskId = (String) params.get("taskId");
		String chuzhang = (String) params.get("chuzhang");
		Task task = this.tc.getTask(Long.parseLong(taskId));
		ItemApproval ia = this.loadItem(task.getBusinessId());
		ItemSetting is = EntityUtils.getValue(ia, "itemSetting");

		TaskPR taskPR = ContextHolder.getApplicationContext().getBean(TaskPR.class);
		taskEntity.setSourceUrl(is.getBusUrl());
		taskEntity.setSourceTable(Class.forName(ia.getBusEntityClass()).getAnnotation(Table.class).name());
		taskEntity.setSourceKey(ia.getBusKey());
		taskEntity.setSourceDesc(is.getName() + "(" + ia.getName() + ")");
		taskEntity.setState(10);
		taskPR.updateTask(taskEntity);

		if (StringUtils.isNotEmpty(chuzhang)) {
			this.pc.saveProcessVariable(task.getProcessInstanceId(), "taskEntityChuzhang", chuzhang);
		}
		this.pc.saveProcessVariable(task.getProcessInstanceId(), "taskEntity", taskEntity);
		this.tc.start(task.getId());
		this.tc.complete(task.getId(), "任务管理");
	}

	/**
	 * 发起事项审批流程
	 * 
	 * @param itemApprovalId
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void startProcess(Map<String, Object> params) throws Exception {
		String itemApprovalId = (String) params.get("itemApprovalId");
		String taskId = (String) params.get("taskId");
		String shenhekz = (String) params.get("shenhekz");
		String shenheCz = (String) params.get("shenheCz");
		boolean shouldKz = (boolean) params.get("shouldKz");
		ItemApproval ia = (ItemApproval) this.itemApprovalDao.get(itemApprovalId, ItemApproval.class);
		Map<String, Object> variables = new HashMap<String, Object>();
		if (StringUtils.isNotEmpty(taskId)) {
			// 如果taskId不为空
			if (shouldKz) {
				variables.put("shenhekz", shenhekz);
			}
			variables.put("shenheCz", shenheCz);
			variables.put("shouldKz", shouldKz);
			variables.put("agree", 1);
			params.put("businessId", itemApprovalId);
			params.put("opinion", "修改后再次提交申请");
			params.put("variables", variables);
			this.completeTask(this.tc.getTask(Long.parseLong(taskId)), null, "修改后再次提交申请", false, null, variables);
		} else {
			if (ia.getState()!=0) {
				throw new Exception("当前数据已经发起过流程，不能重新发起！");
			}
			// 默认的事项开始流程
			StartProcessInfo spi = new StartProcessInfo();
			spi.setBusinessId(itemApprovalId);
			spi.setPromoter(ContextHolder.getLoginUserName());
			spi.setCompleteStartTask(true);

			Dept dept = (Dept) ContextHolder.getLoginUser().getDepts().get(0);
			if (dept.getLevel() == 0 || dept.getLevel() == 1) {
				// 南宁
				variables.put("nanning", true);
			} else {
				variables.put("nanning", false);
			}

			if (shouldKz) {
				variables.put("shenhekz", shenhekz);
			}
			variables.put("shenheCz", shenheCz);
			variables.put("shouldKz", shouldKz);
			spi.setVariables(variables);
			this.pc.startProcessByName("事项审批流程", spi);
		}

		ia.setState(10);
		this.itemApprovalDao.update(ia);
	}

	/**
	 * 撤销申请
	 * 
	 * @param params
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void cancelApply(Map<String, Object> params) throws Exception {
		String businessId = (String) params.get("businessId");
		String taskid = params.get("taskId").toString();
		String opinion = (String) params.get("opinion");
		long taskId = Long.parseLong(taskid);

		ItemApproval ia = this.itemApprovalDao.get(businessId, ItemApproval.class);
		ia.setState(20);
		this.itemApprovalDao.update(ia);

		Task task = this.tc.getTask(taskId);

		Opinion o = new Opinion();
		o.setBusKey(businessId);
		o.setBusTable(GetTableUtils.getTablename(ItemApproval.class));
		o.setCname(ContextHolder.getLoginUser().getCname());
		o.setUsername(ContextHolder.getLoginUserName());
		o.setDeptId(ContextHolder.getLoginUser().getDepts().get(0).getId());
		o.setDeptName(ContextHolder.getLoginUser().getDepts().get(0).getName());
		o.setOpinion(StringUtils.isEmpty(opinion) ? "申请人撤销流程！" : opinion);
		o.setProcessInstanceId(task.getProcessInstanceId());
		o.setProcessName(this.pc.getProcessById(task.getProcessId()).getName());
		o.setTaskId(task.getId());
		o.setTaskName(task.getTaskName());
		o.setNodeName(task.getNodeName());
		this.coreHibernateDao.save(o);

		this.tc.forward(taskId, "结束");
	}

	/**
	 * 申请部门科长审核
	 * 
	 * @param params
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void completeTaskByKz(Map<String, Object> params) throws Exception {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");
		int agree = Integer.parseInt(params.get("agree").toString());

		Task task = this.tc.getTask(taskId);
		String businessId = task.getBusinessId();
		ItemApproval itemApproval = this.itemApprovalDao.get(businessId, ItemApproval.class);
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("agree", agree);
		if (agree == 0) {
			String reStart = "科长驳回" + itemApproval.getTypeName() + "【" + itemApproval.getName() + "】";
			variables.put("reStart", reStart);
		}
		Opinion o = this.completeTask(task, null, opinion, false, null, variables);

		Collection<ICompleteTaskByKzService> ctksCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskByKzService.class).values();
		if (ctksCol != null && !ctksCol.isEmpty()) {
			for (ICompleteTaskByKzService ctks : ctksCol) {
				if (ctks.support(itemApproval.getBusEntityClass())) {
					ctks.execute(o);
				}
			}
		}
	}

	/**
	 * 申请部门处长审核
	 * 
	 * @param params
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void completeTaskByCz(Map<String, Object> params) throws Exception {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");
		int agree = Integer.parseInt(params.get("agree").toString());

		Task task = this.tc.getTask(taskId);
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("agree", agree);

		String businessId = task.getBusinessId();
		ItemApproval itemApproval = this.itemApprovalDao.get(businessId, ItemApproval.class);

		Opinion o = null;
		if (agree == 0) {
			String reStart = "被驳回，需要修改内容重新申请" + itemApproval.getTypeName() + "【" + itemApproval.getName() + "】";
			variables.put("reStart", reStart);
			o = this.completeTask(task, null, opinion, true, null, variables);
		} else {
			String sqbmzhyTaskName = "综合员处理" + itemApproval.getTypeName() + "【" + itemApproval.getName() + "】";
			variables.put("sqbmzhyTaskName", sqbmzhyTaskName);
			o = this.completeTask(task, null, opinion, false, "通过", variables);
		}

		Collection<ICompleteTaskByCzService> ctcsCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskByCzService.class).values();
		if (ctcsCol != null && !ctcsCol.isEmpty()) {
			for (ICompleteTaskByCzService ctcs : ctcsCol) {
				if (ctcs.support(itemApproval.getBusEntityClass())) {
					ctcs.execute(o);
				}
			}
		}
	}

	/**
	 * 申请部门综合员处理
	 * 
	 * @param params
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void completeTaskByZhy(Map<String, Object> params) throws Exception {
		String deptId = (String) params.get("deptId");
		String deptName = (String) params.get("deptName");
		String acceptDeptId = (String) params.get("acceptDeptId");
		if (StringUtils.isNotEmpty(acceptDeptId)) {
			AcceptDept ad = this.itemApprovalDao.get(acceptDeptId, AcceptDept.class);
			ad.setDeptId(deptId);
			ad.setDeptName(deptName);
			this.itemApprovalDao.update(ad);
		}
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");
		String nextDeptId = deptId;

		Task task = this.tc.getTask(taskId);
		Map<String, Object> variables = new HashMap<String, Object>();
		// variables.put("agree", 1);
		variables.put("nextDept", this.getNextDeptInfo(task.getBusinessId(), nextDeptId));

		String businessId = task.getBusinessId();
		ItemApproval itemApproval = this.itemApprovalDao.get(businessId, ItemApproval.class);
		String startDept = ContextHolder.getLoginUser().getDepts().get(0).getName();
		startDept = "";
		String xgzhy = "需要处理：" + startDept + itemApproval.getTypeName() + "【" + itemApproval.getName() + "】";
		variables.put("xgzhy", xgzhy);
		variables.put("startDept", startDept);
		Opinion o = this.completeTask(task, null, opinion, false, "子流程", variables);

		Collection<ICompleteTaskByZhyService> ctcsCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskByZhyService.class).values();
		if (ctcsCol != null && !ctcsCol.isEmpty()) {
			for (ICompleteTaskByZhyService ctcs : ctcsCol) {
				if (ctcs.support(itemApproval.getBusEntityClass())) {
					ctcs.execute(o);
				}
			}
		}
	}

	/**
	 * 申请部门综合员直接完成任务，结束流程
	 * 
	 * @param params
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void completeTaskByZhyEndProcess(Map<String, Object> params) throws Exception {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");
		int agree = Integer.parseInt(params.get("agree").toString());

		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("agree", agree);
		Task task = this.tc.getTask(taskId);
		Opinion o = this.completeTask(task, null, opinion, false, "结束", variables);

		Collection<ICompleteTaskByZhyEndProcessService> ctcsCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskByZhyEndProcessService.class).values();
		if (ctcsCol != null && !ctcsCol.isEmpty()) {
			for (ICompleteTaskByZhyEndProcessService ctcs : ctcsCol) {
				if (ctcs.support(
						this.itemApprovalDao.get(task.getBusinessId(), ItemApproval.class).getBusEntityClass())) {
					ctcs.execute(o);
				}
			}
		}
	}

	/**
	 * 盖章员盖完章
	 * 
	 * @param params
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void completeTaskByStamp(Map<String, Object> params) throws Exception {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");

		Task task = this.tc.getTask(taskId);
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("stamped", true);
		Opinion o = this.completeTask(task, null, opinion, true, null, variables);

		Collection<ICompleteTaskByStampService> ctcsCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskByStampService.class).values();
		if (ctcsCol != null && !ctcsCol.isEmpty()) {
			for (ICompleteTaskByStampService ctcs : ctcsCol) {
				if (ctcs.support(
						this.itemApprovalDao.get(task.getBusinessId(), ItemApproval.class).getBusEntityClass())) {
					ctcs.execute(o);
				}
			}
		}
	}

	/**
	 * 需要盖章，完成本次任务，转到盖章员处
	 * 
	 * @param params
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void complteTaskByShouldStamp(Map<String, Object> params) throws Exception {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");
		Task task = this.tc.getTask(taskId);
		Map<String, Object> variables = new HashMap<String, Object>();
		String businessId = task.getBusinessId();
		// taskService.getUserData(arg0, arg1)
		// processService.getProcessVariables(arg0)

		ProcessInstance processInstance = processService.getProcessInstanceById(task.getProcessInstanceId());
		Object processVariable = processService.getProcessVariable("startDept", processInstance);
		ItemApproval itemApproval = this.itemApprovalDao.get(businessId, ItemApproval.class);
		if (processVariable != null) {
			String xggz = "需要盖章：" + processVariable.toString() + itemApproval.getTypeName() + "【"
					+ itemApproval.getName() + "】";
			variables.put("xggz", xggz);
		}
		// System.out.println(processVariable);

		Opinion o = this.completeTask(task, null, opinion, false, "需要盖章", variables);

		Collection<ICompleteTaskByShouldStampService> ctcsCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskByShouldStampService.class).values();
		if (ctcsCol != null && !ctcsCol.isEmpty()) {
			for (ICompleteTaskByShouldStampService ctcs : ctcsCol) {
				if (ctcs.support(itemApproval.getBusEntityClass())) {
					ctcs.execute(o);
				}
			}
		}
	}

	/**
	 * 受理部门综合员不同意，驳回上一步处理人
	 * 
	 * @param params
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void completeTaskBySlZhyDisagree(Map<String, Object> params) throws Exception {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");
		// int agree = Integer.parseInt(params.get("agree").toString());

		Map<String, Object> variables = new HashMap<String, Object>();
		// variables.put("agree", agree);
		variables.put("success", false);
		Task task = this.tc.getTask(taskId);

		String businessId = task.getBusinessId();
		ItemApproval itemApproval = this.itemApprovalDao.get(businessId, ItemApproval.class);

		String sqbmzhyTaskName = "处理部门退回：" + itemApproval.getTypeName() + "【" + itemApproval.getName() + "】";
		variables.put("sqbmzhyTaskName", sqbmzhyTaskName);

		Opinion o = this.completeTask(task, null, opinion, false, "结束", variables);

		Collection<ICompleteTaskBySlZhyDisagreeService> ctcsCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskBySlZhyDisagreeService.class).values();
		if (ctcsCol != null && !ctcsCol.isEmpty()) {
			for (ICompleteTaskBySlZhyDisagreeService ctcs : ctcsCol) {
				if (ctcs.support(itemApproval.getBusEntityClass())) {
					ctcs.execute(o);
				}
			}
		}
	}

	/**
	 * 处理部门综合员直接完成任务，结束流程
	 * 
	 * @param params
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void completeTaskBySlZhyEndProcess(Map<String, Object> params) throws Exception {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");
		// int agree = Integer.parseInt(params.get("agree").toString());

		Task task = this.tc.getTask(taskId);
		Map<String, Object> variables = new HashMap<String, Object>();
		// variables.put("agree", agree);
		variables.put("success", true);
		// String businessId = task.getBusinessId();
		// ItemApproval itemApproval = this.itemApprovalDao.get(businessId,
		// ItemApproval.class);
		// String sqbmzhyTaskName = "受理部门综合员驳回" + itemApproval.getTypeName() +
		// "【" + itemApproval.getName() + "】" ;
		// variables.put("sqbmzhyTaskName", sqbmzhyTaskName);
		Opinion o = this.completeTask(task, null, opinion, false, "结束", variables);

		Collection<ICompleteTaskBySlZhyEndProcessService> ctcsCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskBySlZhyEndProcessService.class).values();
		if (ctcsCol != null && !ctcsCol.isEmpty()) {
			for (ICompleteTaskBySlZhyEndProcessService ctcs : ctcsCol) {
				if (ctcs.support(
						this.itemApprovalDao.get(task.getBusinessId(), ItemApproval.class).getBusEntityClass())) {
					ctcs.execute(o);
				}
			}
		}
	}

	/**
	 * 处理部门综合员需要收集意见，完成本次任务
	 * 
	 * @param users
	 * @param params
	 * @throws Exception
	 */
	@DataResolver
	@Transactional
	public void completeTaskBySlZhyCollectOpinion(List<AcceptUser> users, Map<String, Object> params) throws Exception {
		if ((users == null || users.isEmpty())) {
			throw new Exception("需要征集意见时必须添加征集意见的人！");
		}
		String businessId = (String) params.get("businessId");
		String opinion = (String) params.get("opinion");

		String hql = "select id from " + AcceptDept.class.getName()
				+ " where itemApprovalId=:businessId and deptId=:deptId and invalid=false";
		Map<String, Object> parameter = new HashMap<String, Object>();
		parameter.put("businessId", businessId);
		Dept dept = (Dept) ContextHolder.getLoginUser().getDepts().get(0);
		parameter.put("deptId", dept.getCDept().getId());
		List<String> list = this.itemApprovalDao.query(hql, parameter);
		final String acceptDeptId = list.get(0);

		Map<String, Object> variables = new HashMap<String, Object>();
		// variables.put("collectOpinion", true);// 保存是否收集意见为流程变量
		List<String> uList = new ArrayList<String>();
		for (final AcceptUser user : users) {
			uList.add(user.getUsername());
			user.setAcceptDeptId(acceptDeptId);
			this.itemApprovalDao.save(user);
		}
		variables.put("collectUsers", uList);
		variables.put("withdrawUsers", Collections.EMPTY_LIST);
		// variables.put("agree", 1);
		// variables.put("next", 0);
		long taskId = Long.parseLong(params.get("taskId").toString());
		Task task = this.tc.getTask(taskId);
		ItemApproval itemApproval = this.itemApprovalDao.get(businessId, ItemApproval.class);
		ProcessInstance processInstance = processService.getProcessInstanceById(task.getProcessInstanceId());
		Object processVariable = processService.getProcessVariable("startDept", processInstance);

		String zjyj = "需要给出意见：" + processVariable.toString() + itemApproval.getTypeName() + "【" + itemApproval.getName()
				+ "】";
		variables.put("zjyj", zjyj);
		Opinion o = this.completeTask(this.tc.getTask(Long.parseLong(params.get("taskId").toString())), null, opinion,
				false, "征集意见", variables);

		Collection<ICompleteTaskBySlZhyCollectOpinionService> ctcsCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskBySlZhyCollectOpinionService.class).values();
		if (ctcsCol != null && !ctcsCol.isEmpty()) {
			for (ICompleteTaskBySlZhyCollectOpinionService ctcs : ctcsCol) {
				if (ctcs.support(itemApproval.getBusEntityClass())) {
					ctcs.execute(o);
				}
			}
		}
	}

	/**
	 * 处理部门各个科长给出意见
	 * 
	 * @param users
	 * @param params
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void completeTaskByGiveOpinion(Map<String, Object> params) throws Exception {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");

		Task task = this.tc.getTask(taskId);
		Map<String, Object> variables = new HashMap<String, Object>();

		String businessId = task.getBusinessId();
		ItemApproval itemApproval = this.itemApprovalDao.get(businessId, ItemApproval.class);

		ProcessInstance processInstance = processService.getProcessInstanceById(task.getProcessInstanceId());
		Object processVariable = processService.getProcessVariable("startDept", processInstance);

		// String xgzhyyj = "相关部门综合员审核对" + processVariable.toString() +
		// itemApproval.getTypeName() + "【" + itemApproval.getName() + "】的征集意见";
		String xgzhy = "已收集完相关科室意见，需要审核收集的意见：" + itemApproval.getTypeName() + "【" + itemApproval.getName() + "】";

		variables.put("xgzhy", xgzhy);
		Opinion o = this.completeTask(task, null, opinion, false, null, variables);

		Collection<ICompleteTaskByGiveOpinionService> ctcsCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskByGiveOpinionService.class).values();
		if (ctcsCol != null && !ctcsCol.isEmpty()) {
			for (ICompleteTaskByGiveOpinionService ctcs : ctcsCol) {
				if (ctcs.support(itemApproval.getBusEntityClass())) {
					ctcs.execute(o);
				}
			}
		}
	}

	/**
	 * 处理部门综合员重新征集的意见，完成本次任务
	 * 
	 * @param users
	 * @param params
	 * @throws Exception
	 */
	@DataResolver
	@Transactional
	public void completeTaskBySlZhyReCollectOpinion(List<AcceptUser> users, Map<String, Object> params)
			throws Exception {
		String businessId = (String) params.get("businessId");
		List<String> withdrawUsers = new ArrayList<String>();// 存放被驳回的或者新加的科长
		for (AcceptUser user : users) {
			if (EntityState.MODIFIED == EntityUtils.getState(user)) {
				if (EntityUtils.getBoolean(user, "withdraw")) {
					withdrawUsers.add(user.getUsername());
				}
			} else if (EntityState.NEW == EntityUtils.getState(user)) {
				withdrawUsers.add(user.getUsername());

				String hql = "select id from " + AcceptDept.class.getName()
						+ " where itemApprovalId=:businessId and deptId=:deptId and invalid=false";
				Map<String, Object> parameter = new HashMap<String, Object>();
				parameter.put("businessId", businessId);
				Dept dept = (Dept) ContextHolder.getLoginUser().getDepts().get(0);
				parameter.put("deptId", dept.getCDept().getId());
				List<String> list = this.itemApprovalDao.query(hql, parameter);
				final String acceptDeptId = list.get(0);
				user.setAcceptDeptId(acceptDeptId);
				this.itemApprovalDao.save(user);
			}
		}
		String opinion = (String) params.get("opinion");
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("withdrawUsers", withdrawUsers);
		// variables.put("agree", 0);
		// variables.put("backFlow", 1);

		ItemApproval itemApproval = this.itemApprovalDao.get(businessId, ItemApproval.class);
		Task task = this.tc.getTask(Long.parseLong(params.get("taskId").toString()));
		ProcessInstance processInstance = processService.getProcessInstanceById(task.getProcessInstanceId());
		Object processVariable = processService.getProcessVariable("startDept", processInstance);

		// String zjyj = "对" + processVariable.toString() +
		// itemApproval.getTypeName() + "【" + itemApproval.getName() +
		// "】重新征集意见";
		String zjyj = "需要重新给出意见：" + itemApproval.getTypeName() + "【" + itemApproval.getName() + "】";
		variables.put("zjyj", zjyj);

		Opinion o = this.completeTask(task, null, opinion, false, "重新征集意见", variables);

		Collection<ICompleteTaskBySlZhyReCollectOpinionService> ctcsCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskBySlZhyReCollectOpinionService.class).values();
		if (ctcsCol != null && !ctcsCol.isEmpty()) {
			for (ICompleteTaskBySlZhyReCollectOpinionService ctcs : ctcsCol) {
				if (ctcs.support(itemApproval.getBusEntityClass())) {
					ctcs.execute(o);
				}
			}
		}
	}

	/**
	 * 处理部门综合员完成本次任务，流转到下一部门
	 * 
	 * @param params
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void complateTaskBySlZhyToNextDept(Map<String, Object> params) throws Exception {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");
		String deptId = (String) params.get("deptId");
		int from = Integer.parseInt(params.get("from").toString());
		Task task = this.tc.getTask(taskId);
		Map<String, Object> variables = new HashMap<String, Object>();
		// variables.put("agree", 1);
		// variables.put("next", 1);
		variables.put("from", from);
		variables.put("nextDept", this.getNextDeptInfo(task.getBusinessId(), deptId));

		String businessId = task.getBusinessId();
		ItemApproval itemApproval = this.itemApprovalDao.get(businessId, ItemApproval.class);

		ProcessInstance processInstance = processService.getProcessInstanceById(task.getProcessInstanceId());
		Object processVariable = processService.getProcessVariable("startDept", processInstance);

		String xgzhy = "需要处理：" + itemApproval.getTypeName() + "【" + itemApproval.getName() + "】";
		variables.put("xgzhy", xgzhy);

		Opinion o = this.completeTask(task, null, opinion, false, "子流程", variables);

		Collection<ICompleteTaskBySlZhyToNextDeptService> ctcsCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskBySlZhyToNextDeptService.class).values();
		if (ctcsCol != null && !ctcsCol.isEmpty()) {
			for (ICompleteTaskBySlZhyToNextDeptService ctcs : ctcsCol) {
				if (ctcs.support(itemApproval.getBusEntityClass())) {
					ctcs.execute(o);
				}
			}
		}
	}

	/**
	 * 处理部门综合员完成本次任务，提交给部门领导审查
	 * 
	 * @param params
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void complateTaskBySlZhyToLeader(Map<String, Object> params) throws Exception {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");
		String chuzhang = (String) params.get("chuzhang");
		Task task = this.tc.getTask(taskId);
		Map<String, Object> variables = new HashMap<String, Object>();
		// variables.put("agree", 1);
		// variables.put("next", 0);
		variables.put("shenheCz", chuzhang);

		String businessId = task.getBusinessId();
		ItemApproval itemApproval = this.itemApprovalDao.get(businessId, ItemApproval.class);

		ProcessInstance processInstance = processService.getProcessInstanceById(task.getProcessInstanceId());
		Object processVariable = processService.getProcessVariable("startDept", processInstance);
		processVariable = "";
		String xgczsh = "需要审核：" + processVariable.toString() + itemApproval.getTypeName() + "【" + itemApproval.getName()
				+ "】";
		variables.put("xgczsh", xgczsh);

		Opinion o = this.completeTask(task, null, opinion, false, "提交部门领导", variables);

		Collection<ICompleteTaskBySlZhyToLeaderService> ctcsCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskBySlZhyToLeaderService.class).values();
		if (ctcsCol != null && !ctcsCol.isEmpty()) {
			for (ICompleteTaskBySlZhyToLeaderService ctcs : ctcsCol) {
				if (ctcs.support(itemApproval.getBusEntityClass())) {
					ctcs.execute(o);
				}
			}
		}
	}

	/**
	 * 处理部门处长审核
	 * 
	 * @param params
	 * @throws Exception
	 */
	@Expose
	@Transactional
	public void completeTaskBySlCz(Map<String, Object> params) throws Exception {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");
		int agree = Integer.parseInt(params.get("agree").toString());

		Task task = this.tc.getTask(taskId);
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("agree", agree);
		String businessId = task.getBusinessId();
		ItemApproval itemApproval = this.itemApprovalDao.get(businessId, ItemApproval.class);

		ProcessInstance processInstance = processService.getProcessInstanceById(task.getProcessInstanceId());
		Object processVariable = processService.getProcessVariable("startDept", processInstance);
		processVariable = "";
		if (agree == 1) {
			String xgzhy = "需要继续处理：" + processVariable.toString() + itemApproval.getTypeName() + "【"
					+ itemApproval.getName() + "】";
			variables.put("xgzhy", xgzhy);
		} else {
			String xgzhy = "处长驳回：" + processVariable.toString() + itemApproval.getTypeName() + "【"
					+ itemApproval.getName() + "】";
			variables.put("xgzhy", xgzhy);
		}

		Opinion o = this.completeTask(task, null, opinion, true, null, variables);

		Collection<ICompleteTaskBySlCzService> ctcsCol = ContextHolder.getApplicationContext()
				.getBeansOfType(ICompleteTaskBySlCzService.class).values();
		if (ctcsCol != null && !ctcsCol.isEmpty()) {
			for (ICompleteTaskBySlCzService ctcs : ctcsCol) {
				if (ctcs.support(itemApproval.getBusEntityClass())) {
					ctcs.execute(o);
				}
			}
		}
	}

	private Opinion completeTask(Task task, String taskName, String opinion, boolean withdraw, String flowName,
			Map<String, Object> variables) {
		Opinion o = this.saveOpinion(task, taskName, opinion);
		if (withdraw) {
			if (variables == null || variables.isEmpty()) {
				this.tc.withdraw(task.getId());
			} else {
				this.tc.withdraw(task.getId(), variables);
			}
		} else {
			this.tc.start(task.getId());
			if (StringUtils.isEmpty(flowName)) {
				if (variables == null || variables.isEmpty()) {
					this.tc.complete(task.getId());
				} else {
					this.tc.complete(task.getId(), variables);
				}
			} else {
				if (variables == null || variables.isEmpty()) {
					this.tc.complete(task.getId(), flowName);
				} else {
					this.tc.complete(task.getId(), flowName, variables);
				}
			}
		}
		return o;
	}

	private Opinion saveOpinion(Task task, String taskName, String opinion) {
		ItemApproval ia = (ItemApproval) this.itemApprovalDao.get(task.getBusinessId(), ItemApproval.class);
		Opinion o = new Opinion();
		o.setBusKey(task.getBusinessId());
		o.setBusTable(GetTableUtils.getTablename(ItemApproval.class));
		o.setOpinion(opinion);
		o.setProcessInstanceId(task.getProcessInstanceId());
		o.setProcessName("事项审批流程--" + this.itemApprovalDao.getItemSeting(ia.getType()).getName());
		o.setTaskId(task.getId());
		o.setTaskName(StringUtils.isEmpty(taskName) ? task.getTaskName() : taskName);
		o.setNodeName(task.getNodeName());
		o.setUsername(ContextHolder.getLoginUserName());
		o.setCname(ContextHolder.getLoginUser().getCname());
		o.setDeptId(ContextHolder.getLoginUser().getDepts().get(0).getId());
		o.setDeptName(ContextHolder.getLoginUser().getDepts().get(0).getName());
		this.coreHibernateDao.save(o);
		return o;
	}

	private Map<String, Object> getNextDeptInfo(String businessId, String nextDeptId) {
		Map<String, Object> nextDeptMap = new HashMap<String, Object>();
		String deptId = nextDeptId;
		IDeptService ds = ContextHolder.getBean(IDeptService.BEAN_ID);
		Dept nextDept = ((Dept) ds.loadDeptById(deptId));
		Dept nextCDept = (Dept) nextDept.getCDept();
		List<IUser> zhyList = SecurityUtils.getUserByRoleForDeptWithChildren(nextCDept.getId(), Constants.ROLE_ZHY);
		List<IUser> czList = SecurityUtils.getUserByRoleForDeptWithChildren(nextCDept.getId(), Constants.ROLE_CZ);

		List<String> zhy = new ArrayList<String>();
		for (IUser u : zhyList) {
			zhy.add(u.getUsername());
		}
		List<String> cz = new ArrayList<String>();
		for (IUser u : czList) {
			cz.add(u.getUsername());
		}
		nextDeptMap.put("zhy", zhy);
		nextDeptMap.put("cz", cz);

		String hql = "select count(*) from " + AcceptDept.class.getName()
				+ " where deptId=:deptId and itemApprovalId=:itemApprovalId and invalid=false";
		Map<String, Object> parameterMap = new HashMap<String, Object>();
		parameterMap.put("deptId", nextCDept.getId());
		parameterMap.put("itemApprovalId", businessId);
		if (this.itemApprovalDao.queryForInt(hql, parameterMap) == 0) {
			AcceptDept ad = new AcceptDept();
			ad.setItemApprovalId(businessId);
			ad.setDeptId(nextCDept.getId());
			ad.setDeptName(nextCDept.getName());
			this.itemApprovalDao.save(ad);
		}

		return nextDeptMap;
	}

	/**
	 * 受理部门综合员要征集意见时加载可以征集意见的科长
	 */
	@Override
	public void loadUsers(Page<IUser> page, Criteria criteria, Map<String, Object> params) throws Exception {
		Dept dept = (Dept) ContextHolder.getLoginUser().getDepts().get(0);
		dept = (Dept) dept.getCDept();
		SecurityUtils.getUserByRoleForDeptWithChildren(dept.getId(), Constants.ROLE_KZ, page);
	}

	@Expose
	@Transactional
	public void deleteAcceptUser(String id) {
		this.itemApprovalDao.delete(id, AcceptUser.class);
	}
}
